#include <cmath>
#include <cstdlib>
#include <iterator>
#include "line.h"

line_t::line_t() : a_(.0), b_(.0), c_(.0)
{
}

line_t::line_t(point_t const & first, point_t const & second)
{
    a_ = first.y - second.y;
    b_ = second.x - first.x;
    c_ = second.x * first.y - first.x * second.y;
}

point_pos line_t::classify(point_t const & point) const
{
    double d = distance(*this, point);
    if(d == 0)
        return ON;
    if((d < 0 && a_ > 0) || (d > 0 && a_ < 0))
        return LEFT;
    return RIGHT;
}

bool intersects(line_t const & a, line_t const & b, point_t & intersection)
{
    double denominator = a.a_ * b.b_ - a.b_ * b.a_;
    if(!denominator)
        return false;
    intersection.x = (a.c_ * b.b_ - a.b_ * b.c_) / denominator;
    intersection.y = (a.a_ * b.c_ - a.c_ * b.a_) / denominator;
    return true;
}

bool line_t::is_vertical() const
{
    return (b_ == 0);
}

bool line_t::is_horizontal() const
{
    return (a_ == 0);
}


bool line_t::is_vertical(double & x) const
{
    if (b_ == 0)
    {
        x = c_/a_;
    }
    return (b_ == 0);
}

bool line_t::is_horizontal(double & y) const
{
    if (a_ == 0)
    {
        y = c_ / b_;
    }
    return (a_ == 0);
}

double line_t::get_y(double x) const
{
    if(b_ != 0)
        return (c_ - a_*x) / b_;
    return 0;
}

double line_t::get_x(double y) const
{
    if(a_ != 0)
        return (c_ - b_*y) / a_;
    return 0;
}

double distance(line_t const & line, point_t const & point)
{
    double denominator = sqrt(line.a_ * line.a_ + line.b_ * line.b_);
    double numerator = (line.a_ * point.x + line.b_ * point.y - line.c_);
    return numerator / denominator;
}

double angle(line_t const & l, line_t const & r)
{
    double f = abs(l.a_ * r.a_ + l.b_ * r.b_) / sqrt(l.a_ * l.a_ + l.b_ * l.b_) / sqrt(r.a_ * r.a_ + r.b_ * r.b_);
    return acos(f);
}
